home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / faxd / GettyBSD.c++ < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  211 lines

  1. /*    $Header: /usr/people/sam/fax/faxd/RCS/GettyBSD.c++,v 1.25 1994/02/28 14:15:23 sam Rel $ */
  2. /*
  3.  * Copyright (c) 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25.  
  26. /*
  27.  * FAX Server BSD Getty Support.
  28.  */
  29. #include "GettyBSD.h"
  30.  
  31. #include <stddef.h>
  32. #include <termios.h>
  33. #include <osfcn.h>
  34. #include <sys/wait.h>
  35. #include <sys/stat.h>
  36. #include <sys/ioctl.h>
  37. #include <unistd.h>
  38. #include <paths.h>
  39. #include <time.h>
  40. #include <utmp.h>
  41.  
  42. BSDGetty::BSDGetty(const fxStr& l, const fxStr& s, u_int t) : Getty(l,s,t)
  43. {
  44. }
  45.  
  46. BSDGetty::~BSDGetty()
  47. {
  48. }
  49.  
  50. fxBool
  51. BSDGetty::isBSDGetty()
  52. {
  53.     return (access((char*) getty, X_OK) == 0);
  54. }
  55.  
  56. Getty*
  57. OSnewGetty(const fxStr& dev, const fxStr& speed)
  58. {
  59.     return (BSDGetty::isBSDGetty() ? new BSDGetty(dev, speed) : NULL);
  60. }
  61.  
  62. /*
  63.  * ``Open'' the device and setup the initial tty state
  64.  * so that the normal stdio routines can be used.
  65.  */
  66. void
  67. BSDGetty::setupSession(int modemFd)
  68. {
  69.     int fd;
  70.     /*
  71.      * Close everything down except the modem so
  72.      * that the remote side doesn't get hung up on.
  73.      */
  74.     for (fd = getdtablesize()-1; fd >= 0; fd--)
  75.     if (fd != modemFd)
  76.         (void) close(fd);
  77.     /*
  78.      * Now make the line be the controlling tty
  79.      * and create a new process group/session for
  80.      * the login process that follows.
  81.      */
  82.     fd = open("tty", 0);        // NB: assumes we're in /dev
  83.     if (fd >= 0) {
  84.     (void) ioctl(fd, TIOCNOTTY, 0);
  85.     (void) close(fd);
  86.     }
  87.     (void) setsid();
  88.     fd = open(getLine(), O_RDWR|O_NONBLOCK);
  89.     if (fd != STDIN_FILENO)
  90.     fatal("Can not setup \"%s\" as stdin", getLine());
  91.     if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) &~ O_NONBLOCK))
  92.     fatal("Can not reset O_NONBLOCK: %m");
  93.     close(modemFd);            // done with this, pitch it
  94.  
  95. #ifdef TIOCSCTTY
  96.     if (ioctl(fd, TIOCSCTTY, 0))
  97.     fatal("Cannot set controlling tty: %m");
  98. #endif
  99. #ifdef TIOCGETDFLT
  100.     /*
  101.      * FaxServer::setBaudRate forces CLOCAL on for BSDi.  However
  102.      * getty resets the terminal to the system default, if one exists,
  103.      * prior to execing login, but preserves CLOCAL, if it is on.
  104.      * Thus, if a system default setting exists for the tty, we
  105.      * set the CLOCAL state from it; otherwise, we leave CLOCAL on.
  106.      */
  107.     struct termios term, dflt;
  108.     if (ioctl(fd, TIOCGETDFLT, &dflt) == 0 && (dflt.c_cflag & CLOCAL) == 0) {
  109.     (void) tcgetattr(fd, &term);
  110.     term.c_cflag &= ~CLOCAL;
  111.     (void) tcsetattr(fd, TCSAFLUSH, &term);
  112.     }
  113. #else
  114.     /*
  115.      * Turn off CLOCAL so that SIGHUP is sent on modem disconnect.
  116.      */
  117.     struct termios term;
  118.     if (tcgetattr(fd, &term) == 0) {
  119.     term.c_cflag &= ~CLOCAL;
  120.     (void) tcsetattr(fd, TCSAFLUSH, &term);
  121.     }
  122. #endif
  123.     /*
  124.      * Setup descriptors for stdout, and stderr.
  125.      * Establish the initial line termio settings and set
  126.      * protection on the device file.
  127.      */
  128.     struct stat sb;
  129.     (void) stat(getLine(), &sb);
  130.     (void) chown(getLine(), 0, sb.st_gid);
  131.     (void) chmod(getLine(), 0622);
  132.     if (dup2(fd, STDOUT_FILENO) < 0)
  133.     fatal("Unable to dup stdin to stdout: %m");
  134.     if (dup2(fd, STDERR_FILENO) < 0)
  135.     fatal("Unable to dup stdin to stderr: %m");
  136. }
  137.  
  138. #ifdef __bsdi__
  139. extern "C" int logout(const char*);
  140. extern "C" int logwtmp(const char*, const char*, const char*);
  141. #endif
  142.  
  143. #define    lineEQ(a,b)    (strncmp(a,b,sizeof(a)) == 0)
  144.  
  145. void
  146. BSDGetty::writeWtmp(utmp* ut)
  147. {
  148. #ifndef __bsdi__
  149.     int wfd = open(_PATH_WTMP, O_WRONLY|O_APPEND);
  150.     if (wfd >= 0) {
  151.     struct stat buf;
  152.     if (fstat(wfd, &buf) == 0) {
  153.         memset(ut->ut_name, 0, sizeof (ut->ut_name));
  154.         memset(ut->ut_host, 0, sizeof (ut->ut_host));
  155.         ut->ut_time = time(0);
  156.         if (write(wfd, (char *)ut, sizeof (*ut)) != sizeof (*ut))
  157.         (void) ftruncate(wfd, buf.st_size);
  158.     }
  159.     (void) close(wfd);
  160.     }
  161. #else
  162.     logwtmp(ut->ut_line, "", "");
  163. #endif
  164. }
  165.  
  166. void
  167. BSDGetty::logout(const char* line)
  168. {
  169. #ifndef __bsdi__
  170.     int ufd = open(_PATH_UTMP, O_RDWR);
  171.     if (ufd >= 0) {
  172.     struct utmp ut;
  173.     while (read(ufd, (char *)&ut, sizeof (ut)) == sizeof (ut))
  174.         if (ut.ut_name[0] && lineEQ(ut.ut_line, line)) {
  175.         memset(ut.ut_name, 0, sizeof (ut.ut_name));
  176.         memset(ut.ut_host, 0, sizeof (ut.ut_host));
  177.         ut.ut_time = time(0);
  178.         (void) lseek(ufd, -(long) sizeof (ut), SEEK_CUR);
  179.         (void) write(ufd, (char *)&ut, sizeof (ut));
  180.         }
  181.     (void) close(ufd);
  182.     }
  183. #else
  184.     ::logout(line);
  185. #endif
  186. }
  187.  
  188. void
  189. BSDGetty::hangup()
  190. {
  191.     // at this point we're root and we can reset state
  192.     int ufd = open(_PATH_UTMP, O_RDONLY);
  193.     if (ufd >= 0) {
  194.     struct utmp ut;
  195.     while (read(ufd, (char *)&ut, sizeof (ut)) == sizeof (ut))
  196.         if (ut.ut_name[0] && lineEQ(ut.ut_line, getLine())) {
  197.         writeWtmp(&ut);
  198.         break;
  199.         }
  200.     (void) close(ufd);
  201.     }
  202.     logout(getLine());
  203.     Getty::hangup();
  204. }
  205.  
  206. fxBool
  207. BSDGetty::wait(int& status, fxBool block)
  208. {
  209.     return (waitpid(getPID(), &status, block ? 0 : WNOHANG) == getPID());
  210. }
  211.